#include "grate/util/ext_rational.h"

#include <sstream>
#include <string>
#include "grate/util/common.h"

namespace growth_rate {

static inline uint64_t gcd(uint64_t a, uint64_t b) {
  return (b == 0) ? a : gcd(b, a % b);
}

ExtendedRational::ExtendedRational()
    : num(0), denum(1), plus(false) {}

ExtendedRational::ExtendedRational(uint64_t x)
    : num(x), denum(1), plus(false) {}

ExtendedRational::ExtendedRational(uint64_t num, uint64_t denum, bool plus)
    : num(num), denum(denum), plus(plus) {
  CHECK_GT(denum, 0);
}

ExtendedRational ExtendedRational::multiply(
    const ExtendedRational& other) const {
  uint64_t n = num * other.num;
  uint64_t d = denum * other.denum;
  uint64_t g = gcd(n, d);
  return ExtendedRational(n / g, d / g, plus && other.plus);
}

int64_t ExtendedRational::compare(const ExtendedRational& other) const {
  int64_t left = 2 * (num * other.denum) + plus;
  int64_t right = 2 * (denum * other.num) + other.plus;
  return left - right;
}

uint64_t ExtendedRational::int_value() const {
  CHECK_GT(denum, 0);
  return num / denum;
}

std::string ExtendedRational::dump() const {
  std::stringstream out;
  uint64_t g = gcd(num, denum);
  out << (num / g);
  if (denum / g > 1) {
    out << "/" << (denum / g);
  }
  if (plus) {
    out << "+";
  }
  return out.str();
}

}  // namespace growth_rate
